<?php

class EntityModel extends DomObjModel
{

  /**
   *
   * @return Entity
   */
  public function factory($model = null, $data = null)
  {
    $class = $this->getClass();

    if ($class) {
      $obj = new $class($data);
    }
    else {
      $obj = new CustomEntity($model, $data);
    }

    return $obj;
  }

  /**
   *
   * @return string
   */
  public function getPk()
  {
    if (isset($this->model['pk'])) {
      $pk = $this->model['pk'];

      try {
        $this->getField($pk);
      }
      catch (FieldNotFoundException $e) {
        throw new DomainDefinitionException('Could not determine primary key');
      }
    }
    else {
      try {
        $this->getField('id');
        $pk = 'id';
      }
      catch (FieldNotFoundException $e) {
        try {
          $pk = Inflector::underscore($this->getName() . '_id');
          $this->getField($pk);
        }
        catch (FieldNotFoundException $e) {
          throw new DomainDefinitionException('Could not determine primary key');
        }
      }
    }

    return $pk;
  }

  /**
   *
   * @return string
   */
  public function getTable($i = 0)
  {
    $table = $this->getTables();

    if (is_array($table)) {
      $table = $table[$i];
    }

    if (empty($table)) {
      $table = $this->getField($this->getPk())->getTable();
    }

    return $table;
  }

  /**
   *
   * @return array
   */
  public function getFields()
  {
    return $this->model['fields'];
  }

  /**
   *
   * @return FieldModel
   */
  public function getPkField()
  {
    return $this->getField($this->getPk());
  }

  /**
   *
   * @return void
   */
  public function fieldExists($name)
  {
    if (! isset($this->model['fields'][$name])) {
      throw new FieldNotFoundException("Field <b>$name</b> not found in entity");
    }
  }

  /**
   *
   * @return FieldModel
   */
  public function getField($name)
  {
    $this->fieldExists($name);

    if (! ($this->model['fields'][$name] instanceof FieldModel)) {
      $this->model['fields'][$name] = new FieldModel($this->model['fields'][$name]);
    }

    return $this->model['fields'][$name];
  }

  /**
   *
   * @return array
   */
  public function getTables()
  {
    if (! isset($this->model['table'])) {
      $tables = array();

      $tables[] = $this->getPkField()->getTable();

      if (empty($tables[0])) {
        $tables[] = Inflector::tableize($this->getName());
      }

      foreach ($this->getFields() as $name => $field) {
        $field = $this->getField($name);
        $tables[] = $field->getTable();
      }

      $tables = array_values(array_unique(array_filter($tables)));

      if (empty($tables)) {
        throw new DomainDefinitionException('Could not determine table name');
      }

      $this->model['table'] = $tables;
    }

    return (array) $this->model['table'];
  }

}
